package controllers;

import classJSON.AvailableProvs;
import com.google.gson.reflect.TypeToken;
import models.*;
import play.libs.F;
import play.mvc.*;
import play.mvc.Scope.Session;
import java.util.*;

/**
 * @author Andriy
 */
@With(Secure.class)
public class StatusController extends Controller {

        /**
         * This method is called when user sign in web service.
         * @return id of declare providers and it coordinates
         * */
        public static void userDeclared(long userId) {
                //long userId = Long.parseLong(Session.current().get("userId"));
                StatusManager.get().signIn(userId);
                List<Trips> trips = Trips.find("select trip from Trips trip where trip.status=? or trip.status=?", Status.p_declared, Status.u_requested).fetch();
                AvailableProvs availableProvs = new AvailableProvs(trips,userId);
                renderJSON(availableProvs);
        }

        /**
         * @param pLat - latitude of provider
         * @param pLong - longitude of provider
         * */
        public static void provDeclared(long provId, float pLat, float pLong) {
                //long provId = Long.parseLong(Session.current().get("provId"));
                StatusManager.get().provDeclared(provId, pLat, pLong);
        }

        /**
         * @param provId -id of provider which was chosen by user
         * @param timeOut - time for provider to accept user request
         * */
        public static void chooseProv(long provId,long userId, String timeOut, double u_lat, double u_long) {
                //long userId = Long.parseLong(Session.current().get("userId"));
                StatusManager.get().userChooseTaxi(userId, provId, u_lat, u_long);
                Integer time = 100;
                try {
                        time = Integer.parseInt(timeOut);
                } catch (NumberFormatException e) {
                        System.out.println("Invalid param time");
                }
                time = time * 1000;
                Timer timer = new Timer();
                TimerTask timerTask = new TimeOut(provId, userId, Status.u_requested);
                timer.schedule(timerTask, time);
        }

        /**
         * @param inf - some information which provider send to user
         * @param time - time which provider need for get to user
         * @param userId - id of user which requested provider
         * */
        public static void provAccept(String inf, String time, long userId,long provId) {
                //long provId = Long.parseLong(Session.current().get("provId"));
                  StatusManager.get().provAccept(inf, time, userId, provId);
                  Integer timeOut = 100;
                  try {
                          timeOut = Integer.parseInt(time);
                  } catch (NumberFormatException e) {
                          System.out.println("Invalid param time");
                  }
                timeOut = timeOut * 1000;
                Timer timer = new Timer();
                TimerTask timerTask = new TimeOut(provId, userId, Status.p_accepted);
                timer.schedule(timerTask, timeOut);
        }

        /**
         * @param userId - id of user which requested provider
         * @param provId - id of provider which didn't accepted user's request
         */
        public static void provAcceptCanceled(long userId, long provId) {
                StatusManager.get().provAcceptCanceled(userId, provId);
        }

        /**
         * @param provId id of provider which was chosen by user
         * */
        public static void userConfirmed(long provId, long userId, float lat, float lng) {
                //long userId = Long.parseLong(Session.current().get("userId"));
                if (Trips.getStatus(provId, userId) == Status.p_accepted) {
                        StatusManager.get().userConfirmed(userId, provId, lat, lng);
                }
        }

        /**
         * @param provId - id of provider which was not suitable for user
         * @param userId - id of user, which cancelled
         * */
        public static void userCanceled(long provId, long userId) {
                //userId = Long.parseLong(Session.current().get("userId"));
              	StatusManager.get().userCanceled(userId, provId);
        }

        /**
         * @param userId - id of user which was locked by provider
         * */
        public static void lockUser(long userId, long provId) {
                //long provId = Long.parseLong(Session.current().get("provId"));
                StatusManager.get().lockedUser(provId, userId);
        }

        /**
         * @param userId - id of user which was locked by provider
         * */
        public static void provReached(long userId,long provId) {
				//long provId = Long.parseLong(Session.current().get("provId"));
                StatusManager.get().provReached(provId, userId);
        }

        /**
         *
         * */
        public static void endTrip(/*long userId*/long provId) {
                //long provId = Long.parseLong(Session.current().get("provId"));
                //Users.delEventStream(userId);
                Provs.delEventStream(provId);
                Trips.setParam(Status.ended, provId);
        }

		public static void u_exit(long userId){
				//long userId = Long.parseLong(Session.current().get("userId"));
				Users.delEventStream(userId);
				Session.current().remove("userId");
		}

        /**
         * This method called when provider sign out web service
         * */
        public static void provExit(long provId) {
                //long provId = Long.parseLong(Session.current().get("provId"));
                Provs.delEventStream(provId);
                Session.current().remove("provId");
        }

        /**
         * @param lastReceived - number of last received event
         * */
        public static void waitProvEvents(long lastReceived, long provId) {
                //long provId = Long.parseLong(Session.current().get("provId"));
				// Here I use continuation to suspend
                // the execution until a new event has been received
                List events = await(StatusManager.get().nextProvEvent(lastReceived, provId));
                renderJSON(events, new TypeToken<List<F.IndexedEvent<StatusManager.Event>>>() {
                }.getType());
        }

        /**
         * @param lastReceived - number of last received event
         * */
        public static void waitUserEvents(long lastReceived, long userId) {
                //long userId = Long.parseLong(Session.current().get("userId"));
                // Here I use continuation to suspend
                // the execution until a new event has been received
                List events = await(StatusManager.get().nextUserEvent(lastReceived, userId));
                renderJSON(events, new TypeToken<List<F.IndexedEvent<StatusManager.Event>>>() {
                }.getType());
        }
}
